﻿using System;
using System.Reflection;
using System.Runtime.Serialization;
using Pfz.Extensions;
using System.Threading;

namespace Pfz.Serialization.BinaryBuiltIn
{
	/// <summary>
	/// Serializer for MethodInfo.
	/// </summary>
	public sealed class MethodInfoSerializer:
		IItemSerializer
	{
		/// <summary>
		/// Gets the singleton instance.
		/// </summary>
		public static readonly MethodInfoSerializer Instance = new MethodInfoSerializer();

		private MethodInfoSerializer()
		{
		}

		/// <summary>
		/// Serializes a method info.
		/// </summary>
		public void Serialize(ConfigurableSerializerBase serializer, MethodInfo item)
		{
			TypeSerializer.Instance.Serialize(serializer, item.ReflectedType);
			serializer.Stream.WriteString(item.Name);
			serializer.InnerSerialize(item.GetParameterTypes());
		}

		/// <summary>
		/// Deserializes a method info.
		/// </summary>
		public MethodInfo Deserialize(ConfigurableSerializerBase deserializer)
		{
			Type type = TypeSerializer.Instance.Deserialize(deserializer);
			string name = deserializer.Stream.ReadString();
			var parameterTypes = (Type[])deserializer.InnerDeserialize();

			var result = type.GetMethod(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, parameterTypes, null);
			if (result == null)
				throw new SerializationException("Can't find property " + name + " on type " + type.FullName);

			return result;
		}

		private static readonly Type _forType = ReflectionHelper.GetMethod(() => Thread.Sleep(0)).GetType();
		Type IItemSerializer.ForType
		{
			get
			{
				return _forType;
			}
		}

		void IItemSerializer.Serialize(ConfigurableSerializerBase serializer, object item)
		{
			Serialize(serializer, (MethodInfo)item);
		}

		object IItemSerializer.Deserialize(ConfigurableSerializerBase deserializer)
		{
			return Deserialize(deserializer);
		}
	}
}
